package impl

import (
	"adam2/internal/domain"
	"adam2/internal/model"
	"anubis-framework/pkg/io"
	"anubis-framework/pkg/util"
	"time"
)

type CommodityFutureDateDataDaoImpl struct {
	*BaseDaoImpl
}

// 返回dao实现类
func GetCommodityFutureDateDataDaoImpl() *CommodityFutureDateDataDaoImpl {
	return &CommodityFutureDateDataDaoImpl{GetBaseDaoImpl()}
}

// 返回表名
func (_commodityFutureDateDataDaoImpl *CommodityFutureDateDataDaoImpl) FindTableName() string {
	return "COMMODITY_FUTURE_DATE_DATA"
}

// 随机选取一个期货code
func (_commodityFutureDateDataDaoImpl *CommodityFutureDateDataDaoImpl) FindRandomCommodityFutureCode(beginDate string, enDate string) string {
	io.Infoln("随机选取一个期货code")

	var code string
	var sql string
	if beginDate != "" && enDate != "" {
		sql = "SELECT * FROM (SELECT distinct t.code FROM commodity_future_date_data t " +
			"where (to_date(?,'yyyy-mm-dd')-(SELECT min(t1.transaction_date) FROM commodity_future_date_data t1 where t1.code=t.code))>=500 " +
			"and to_date(?,'yyyy-mm-dd')<=(SELECT max(t2.transaction_date) FROM commodity_future_date_data t2 where t2.code=t.code) " +
			"ORDER BY DBMS_RANDOM.VALUE) WHERE ROWNUM <= 1"
		_commodityFutureDateDataDaoImpl.db.Raw(sql, beginDate, enDate).Scan(&code)
	} else {
		sql = "SELECT * FROM (SELECT distinct t.code FROM commodity_future_date_data t ORDER BY DBMS_RANDOM.VALUE) WHERE ROWNUM <= 1"
		_commodityFutureDateDataDaoImpl.db.Raw(sql).Scan(&code)
	}
	return code
}

// 根据code和transactionDate，查询前一个交易日的日期
func (_commodityFutureDateDataDaoImpl *CommodityFutureDateDataDaoImpl) FindBeforeOneByCodeAndTransactionDate(code string, transactionDate string) time.Time {
	var beforeDate time.Time
	var sql string = "select t1.transaction_date from (" +
		"select * from commodity_future_date_data t where t.code=? and t.transaction_date<to_date(?,'yyyy-mm-dd') order by t.transaction_date desc) t1 " +
		"where rownum<=1"
	_commodityFutureDateDataDaoImpl.db.Raw(sql, code, transactionDate).Scan(&beforeDate)
	return beforeDate
}

// 查询某个期货的最大日期和最小日期
func (_commodityFutureDateDataDaoImpl *CommodityFutureDateDataDaoImpl) FindMinDateAndMaxDate(code string) domain.MaxDataAndMinData {
	io.Infoln("查询某个期货的最大日期和最小日期")

	var mxDataAndMinData domain.MaxDataAndMinData
	_commodityFutureDateDataDaoImpl.db.Table("commodity_future_date_data").Where("code=?", code).
		Select("min(transaction_date) MIN_DATE, max(transaction_date) MAX_DATE").Find(&mxDataAndMinData)
	return mxDataAndMinData
}

// 根据code、开始时间和结束时间查询数据，并按照日期升序排列
func (_commodityFutureDateDataDaoImpl *CommodityFutureDateDataDaoImpl) FindByCodeBetweenDateOrderByDateAsc(code string, beginDate string, endDate string) model.CommodityFutureDateDataArray {
	io.Infoln("根据code[%s]、开始时间[%s]和结束时间[%s]查询记录", code, beginDate, endDate)

	var commodityFutureDateDataArray model.CommodityFutureDateDataArray
	_commodityFutureDateDataDaoImpl.db.Raw("select * from commodity_future_date_data t "+
		"where t.code=? and t.transaction_date between to_date(?, 'yyyy-mm-dd') and to_date(?, 'yyyy-mm-dd') "+
		"order by t.transaction_date asc",
		code, beginDate, endDate).Find(&commodityFutureDateDataArray)
	return commodityFutureDateDataArray
}

// 查询某个期货下一个交易日记录
func (_commodityFutureDateDataDaoImpl *CommodityFutureDateDataDaoImpl) FindNextByCodeAndDate(code string, date string) model.CommodityFutureDateData {
	var commodityFutureDateData model.CommodityFutureDateData
	_commodityFutureDateDataDaoImpl.db.Raw("select * from ("+
		"select * from COMMODITY_FUTURE_DATE_DATA t where t.CODE=? "+
		"and t.TRANSACTION_DATE>to_date(?,'yyyy-mm-dd') order by t.TRANSACTION_DATE asc) t1 "+
		"where ROWNUM<=1",
		code, date).Find(&commodityFutureDateData)
	return commodityFutureDateData
}

// 根据code和transaction_date查询记录
func (_commodityFutureDateDataDaoImpl *CommodityFutureDateDataDaoImpl) FindByCodeAndTransactionDate(code string, transactionDate string) model.CommodityFutureDateData {
	var commodityFutureDateData model.CommodityFutureDateData
	var _transactionDate time.Time = util.StringToDate(transactionDate)
	_commodityFutureDateDataDaoImpl.db.Where(&model.CommodityFutureDateData{Code: code, TransactionDate: _transactionDate}).First(&commodityFutureDateData)
	return commodityFutureDateData
}
